package main

import "fmt"

func main() {
	// 1. 创建管道，创建管道时指定容量为3（必须指定，否则报错deadlock）
	var ch = make(chan int, 3)

	// 2. 给管道写入数据
	ch <- 10
	ch <- 20
	ch <- 30

	// 3. 获取管道的内容
	var a = <-ch
	fmt.Println(a)
	_ = <-ch
	var c = <-ch
	// 4. 管道遵循先入先出原则
	fmt.Println(c)

	ch <- 40
	ch <- 50
	// 5. 打印管道的长度和容量
	// 管道是引用数据类型：值是地址
	fmt.Printf("值(地址)：%v，容量：%v，长度：%v\n", ch, cap(ch), len(ch))
	fmt.Println("如果管道的长度超过容量了会如何？")
	ch <- 60
	// ch <- 70
	// 直接报错了！
	// fmt.Printf("值(地址)：%v，容量：%v，长度：%v\n", ch, cap(ch), len(ch))
	// fatal error: all goroutines are asleep - deadlock!
	// 这里可以看出，管道的长度不能超过定义的容量。而且我们在创建管道时，必须指定容量

	// 6. 管道的类型（引用数据类型）
	var ch1 = make(chan int, 4)
	var ch2 = ch1
	// 改变ch2，看看是否会影响ch1
	ch2 <- 90
	var d = <-ch1
	fmt.Printf("从ch1中取值：%v\n", d)
	// 这里取出来的值是90，说明ch2和ch1指向的是同一个内存地址，证明管道是引用数据类型

	// 8. 管道的阻塞
	// 当管道内放不下数据时，管道就会阻塞
	// fatal error: all goroutines are asleep - deadlock!
	var ch3 = make(chan string, 2)
	ch3 <- "hello"
	ch3 <- "world"
	var m1 = <-ch3
	var m2 = <-ch3
	fmt.Println(m1)
	fmt.Println(m2)
	// 此时ch3中没有数据，如果又想获取，会怎么样呢？
	// 同样会显示deadlock错误
	// 在没有使用协程的情况下，如果管道内的数据已经全部取出，再想取就会报deadlock错误
	// fatal error: all goroutines are asleep - deadlock!
	var m3 = <-ch3
	fmt.Println(m3)
}
